package SIC.Controleur.OWL;

import java.io.File;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;

import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLOntologyStorageException;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.semanticweb.owlapi.model.PrefixManager;
import org.semanticweb.owlapi.util.DefaultPrefixManager;

import uk.ac.manchester.cs.owl.owlapi.OWLDeclarationAxiomImpl;

import SIC.Modele.Composition;
import SIC.Modele.Data;
import SIC.Modele.Produit;

/**
 * Cette classe génère un fichier OWL avec des produits et des composants
 */
public class GenerationOWL {

	private OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
	
	Data data;
	OWLOntology ontology;
	
	public GenerationOWL() {}
	
	//--------------------------------------------
	//			   	   PRINCIPAL
	//--------------------------------------------
	
	/**
	 * Crée le fichier OWL
	 * @param iri l'iri utilisée
	 * @param nomFichierOWL le nom du fichier OWL
	 */
	public void createOntologie(IRI iri, String nomFichierOWL){
		
		if(data != null && !data.isEmpty())
		{
			
			try {

				//On crée un préfixe pour simplifier l'écriture des iri
				PrefixManager pm = new DefaultPrefixManager(iri.toString());
				
				OWLDataFactory dataFactory = manager.getOWLDataFactory();
				ontology = manager.createOntology(iri);
				
				//Propriété de liaison entre le produit et le sous-produit
				OWLObjectProperty estComposeDe = dataFactory.getOWLObjectProperty(IRI.create(iri + "estComposeDe"));
				
				Map<String, Produit> mapProduits = data.getMapProduits();
				Map<String, Composition> mapCompositions = data.getMapCompositions();
				
				//On boucle sur les différents produits et on regarde s'ils ont des ss-produits
				for(Entry<String, Produit> entry: data.getMapProduits().entrySet())
				{
					String nomProduit = replaceSpecialChars(entry.getValue().getPNom());
					
					OWLClass produit = dataFactory.getOWLClass(nomProduit, pm);
					OWLDeclarationAxiomImpl axiome1 = new OWLDeclarationAxiomImpl(dataFactory, produit, new ArrayList<OWLAnnotation>());
					AddAxiom addAx1 = new AddAxiom(ontology, axiome1);
					manager.applyChange(addAx1);
					
					Composition composition = mapCompositions.get(entry.getValue().getProduitID());
					
					//Si le produit est composé
					if(composition != null)
					{
						for(Produit sousProduit : composition.getProduits())
						{	
							String nomComposant = mapProduits.get(sousProduit.getProduitID()).getPNom();
							nomComposant = replaceSpecialChars(nomComposant);
							
							OWLClass composant = dataFactory.getOWLClass(nomComposant, pm);
							
							OWLClassExpression hasPartSomeProduit = dataFactory.getOWLObjectSomeValuesFrom(estComposeDe, composant);
							
							/*
							 * Tous ce qui contient ce sous-produit représente une classe (mais elle n'existe pas concrètement)
							 * Donc notre produit est une sous-classe de ce sous-produit
							 */
							OWLSubClassOfAxiom axiome2 = dataFactory.getOWLSubClassOfAxiom(produit, hasPartSomeProduit);
							
							AddAxiom addAx2 = new AddAxiom(ontology, axiome2);
							manager.applyChange(addAx2);
						}
					}
					
				}
				
				/*
					------------ SAUVEGARDE DE L'ONTOLOGIE ------------
				*/
				
				File file = new File(nomFichierOWL);
				manager.saveOntology(ontology, IRI.create(file.toURI())); //toURI() pour avoir l'adresse absolue
				
				
			} catch (OWLOntologyCreationException e) {
				System.out.println("Could not create ontology: " + e.getMessage());
			} catch (OWLOntologyStorageException e) {
				e.printStackTrace();
			}
		}
		else
		{
			System.err.println("Aucune donnée à convertir en owl.");
		}
		
	}
	
	/**
	 * Enlève certain caractères, ils sont remplacés par des "-"
	 * @param chaine la chaine en entrée
	 * @return retourne une chaine qui contient des "-" à la place des mauvais caractères 
	 */
	public String replaceSpecialChars(String chaine){
		
		String res = chaine;
		
		res = res.replace(" ", "-");
		res = res.replace("d&#39;", "-");
		res = res.replace("'", "-");
		res = res.replace("\"", "-");
		
		return res;
	}
	
	
	//--------------------------------------------
	//			   	GETTER/SETTER
	//--------------------------------------------
	
	public void setData(Data data) {
		this.data = data;
	}
	
	public OWLOntology getOntology() {
		return ontology;
	}
}
